﻿#pragma once
#include <mutex>

template<class T>
class SmartPtr
{
public:
	SmartPtr(T* ptr=nullptr) :_ptr(ptr)
	{}
	~SmartPtr()
	{
		if (_ptr)
		{
			cout << "delete" << _ptr << endl;
			delete _ptr;
			_ptr = nullptr;
			cout << "SmartP delete success" << endl;
		}
	}
	T& operator*()
	{
		return *_ptr;
	}
	T& operator*()const
	{
		return *_ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
private:
	T* _ptr;
};

namespace myspace
{
	/*C++98 转移管理权*/
	template<class T>
	class Auto_Ptr
	{
	public:
		Auto_Ptr(T* ptr = nullptr) :_ptr(ptr)
		{
		}
		Auto_Ptr(Auto_Ptr<T>& ap) :_ptr(ap._ptr)
		{
			ap._ptr = nullptr;
		}
		~Auto_Ptr()
		{
			if (_ptr)
			{
				cout << "delete" << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
				cout << "AP delete success" << endl;
			}
		}
		T& operator*()
		{
			return *_ptr;
		}
		T& operator*()const
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
		Auto_Ptr<T>& operator=(const Auto_Ptr<T>& ap)
		{
			if (_ptr)
				delete _ptr;
			_ptr = ap._ptr;
			ap._ptr = nullptr;
			return *this;
		}
	private:
		T* _ptr;
	};

	/*C++11 防拷贝*/
	template<class T>
	class Unique_Ptr
	{
	public:
		Unique_Ptr(T* ptr = nullptr) :_ptr(ptr)
		{
		}
		Unique_Ptr(Unique_Ptr<T>& up) = delete;
		Unique_Ptr<T>& operator=(const Unique_Ptr<T>& up) = delete;
		~Unique_Ptr()
		{
			if (_ptr)
			{
				cout << "delete" << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
				cout << "UP delete success" << endl;
			}
		}
		T& operator*()
		{
			return *_ptr;
		}
		T& operator*()const
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
		
	private:
		T* _ptr;
	};


	

	/*C++11 计数引用*/
	template<class T>
	class Shared_Ptr
	{
	public:
		Shared_Ptr(T* ptr = nullptr) :_ptr(ptr),_cp(new int(1)),_pMutex(new mutex)
		{
		}
		Shared_Ptr(Shared_Ptr<T>& sp) :_ptr(sp._ptr), _cp(sp._cp), _pMutex(sp._pMutex)
		{
			add_ref_count();
		}
		Shared_Ptr<T>& operator=(const Shared_Ptr<T>& sp)
		{
			if (this!=&sp)
			{
				Release();
				_ptr = sp._ptr;
				_cp = sp._cp;
				_pMutex = sp._pMutex;
				add_ref_count();
			}
			return *this;
		}
		~Shared_Ptr()
		{
			Release();
		}
		T& operator*()
		{
			return *_ptr;
		}
		T& operator*()const
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
		int use_count()
		{
			return *_cp;
		}
		void add_ref_count()
		{
			_pMutex->lock();
			++(*_cp);
			_pMutex->unlock();
		}
		void Release()
		{
			_pMutex->lock();
			bool flag = false;
			if (--(*_cp) == 0)
			{
				if (_ptr)
				{
					cout << "SP Release delete" << _ptr << endl;
					delete _ptr;
					_ptr = nullptr;
					cout << "SP Release delete success" << endl;
				}
				delete _cp;
				_cp = nullptr;
				flag = true;
				cout << "SP Release count" << endl;
			}
			_pMutex->unlock();
			if (flag == true)
			{
				delete _pMutex;
			}
		}
		T* get_ptr()const
		{
			return _ptr;
		}

	private:
		T* _ptr;
		int* _cp;
		mutex* _pMutex;
	};

	/*C++11 弱指针*/
	template<class T>
	class Weak_Ptr
	{
	public:
		Weak_Ptr() = default;
		Weak_Ptr(const Shared_Ptr<T>& sp):_ptr(sp.get_ptr())
		{ }
		Weak_Ptr<T>operator=(const Shared_Ptr<T> &sp)
		{ 
			_ptr = sp.get_ptr();
			return *this;
		}
		T& operator*()
		{
			return *_ptr;
		}
		T& operator*()const
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
	};
}
